﻿using System;
using System.Linq;
using System.Windows.Controls;
using InseSoft.Models.Entities;
using InseSoft.ViewModels;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using Ninject;

namespace InseSoft.Tests.Unit.ViewModels
{
    [TestClass]
    public class LoginViewModelTest
    {
        private readonly IKernel kernel;
        private LoginViewModel instance;

        public LoginViewModelTest()
        {
            kernel = TestHelper.SetupDIKernel();
        }

        [TestInitialize]
        public void TestInitialize()
        {
            var sessionMock = new Mock<ApplicationSession>();
            kernel.Rebind<ApplicationSession>().ToMethod<ApplicationSession>(c => sessionMock.Object);
            instance = kernel.Get<LoginViewModel>();
        }

        [TestMethod]
        public void Constructor_IsNotLoggedIn_DefaultsTrue()
        {
            Assert.IsTrue(instance.IsNotLoggedIn);
        }

        [TestMethod]
        public void ResetValues_FirstCompanySelected()
        {
            var empresas = Enumerable.Range(5, 10).Select(i => new Empresa { Id = i });
            instance.DbContext.Empresas = new FakeDbSet<Empresa>(empresas);
            var sessionMock = Mock.Get(kernel.Get<ApplicationSession>());
            sessionMock.Setup(x => x.Clear());

            instance.ResetValues();

            Assert.AreEqual(5, instance.SelectedEmpresa.Id);
            Assert.IsFalse(instance.InvalidPassword);
            Assert.IsTrue(instance.IsNotLoggedIn);
            Assert.IsTrue(string.IsNullOrEmpty(instance.User));
            sessionMock.VerifyAll();
        }

        [TestMethod]
        public void AcceptExecute_NoUsers_InvalidPasswordTrue()
        {
            var passwordBox = new PasswordBox();
            instance.DbContext.Usuarios = new FakeDbSet<Usuario>();

            instance.AcceptCommand.Execute(passwordBox);

            Assert.IsTrue(instance.InvalidPassword);
        }

        [TestMethod]
        public void AcceptExecute_InvalidPassword_InvalidPasswordTrue()
        {
            var invalidPassword = Guid.NewGuid().ToString();
            const string validUser = "NombreUsuario0";
            var empresa = new Empresa();
            var passwordBox = new PasswordBox { Password = invalidPassword };
            var users = Enumerable.Range(0, 5)
                          .Select(i => new Usuario
                                              {
                                                  Id = i,
                                                  NombreUsuario = "NombreUsuario" + i,
                                                  Clave = "Clave" + i,
                                                  Empresa = empresa
                                              });
            instance.DbContext.Usuarios = new FakeDbSet<Usuario>(users);
            instance.User = validUser;
            instance.SelectedEmpresa = empresa;

            instance.AcceptCommand.Execute(passwordBox);

            Assert.IsTrue(instance.InvalidPassword);
        }

        [TestMethod]
        public void AcceptExecute_ValidPassword_Success()
        {
            const string password = "Clave0";
            const string validUser = "NombreUsuario0";
            var session = kernel.Get<ApplicationSession>();
            var empresa = new Empresa();
            var passwordBox = new PasswordBox { Password = password };
            var users = Enumerable.Range(0, 5)
                          .Select(i => new Usuario
                          {
                              Id = i,
                              NombreUsuario = "NombreUsuario" + i,
                              Clave = "Clave" + i,
                              Empresa = empresa
                          }).ToList();
            instance.DbContext.Usuarios = new FakeDbSet<Usuario>(users);
            instance.User = validUser;
            instance.SelectedEmpresa = empresa;

            instance.AcceptCommand.Execute(passwordBox);

            Assert.IsFalse(instance.InvalidPassword);
            Assert.IsFalse(instance.IsNotLoggedIn);
            Assert.AreSame(instance.SelectedEmpresa, session.Empresa);
            Assert.AreSame(users[0], session.Usuario);
        }

        

    }
}
